#include "networkwidget.h"
#include "homewidget.h"
#include "statuswidget.h"
#include "mavlinkdataprocessor.h"
#include "pages.h"

QMutex NetworkWidget::mutex;
NetworkWidget* NetworkWidget::instance = NULL;

// 全局变量，供多线程访问
QList<QByteArray *> listUdpReceivedData;
QMutex mutexListUdpReceivedData;
MavlinkDataProcessor *mavlinkDataProcessor = nullptr;

NetworkWidget::NetworkWidget(QWidget *parent) : QWidget(parent)
{
    vBoxLayoutPage = new QVBoxLayout;// 当前页面最外层的纵向布局
    topButtons = new TopButtons(QString::fromStdString(Pages::pagesString[Pages::Networkpage]));
    spacerUnderTopButtons = new QSpacerItem(0,0,QSizePolicy::Fixed,QSizePolicy::Expanding);
    hBoxLayoutUdpPortSetting = new QHBoxLayout;
    lineEditUdpPortSetting = new QLineEdit;
    buttonUdpPortSetting = new QPushButton("set");
    labelUdpPortSetting = new QLabel("UDP Port:");
    textEditUdpReceivedData = new QTextEdit;
    udpSocket = nullptr;
    udpReceivedTotalLength = 0;

    // 当前界面最外层布局
    vBoxLayoutPage->setMargin(0);// 每一个layout都要设置间距为0
    vBoxLayoutPage->setSpacing(0);

    // 添加顶部按钮
    vBoxLayoutPage->addLayout(topButtons);
    vBoxLayoutPage->addSpacerItem(spacerUnderTopButtons);

    // 添加配置文件的设置
    hBoxLayoutUdpPortSetting->setMargin(0);
    hBoxLayoutUdpPortSetting->setSpacing(0);
    lineEditUdpPortSetting->setText("14550");
    // 限制端口号输入范围
    lineEditUdpPortSetting->setValidator(new QIntValidator(0, 65535, this));
    hBoxLayoutUdpPortSetting->addWidget(labelUdpPortSetting);
    hBoxLayoutUdpPortSetting->addWidget(lineEditUdpPortSetting);
    hBoxLayoutUdpPortSetting->addWidget(buttonUdpPortSetting);
    connect(buttonUdpPortSetting, &QPushButton::clicked, this, &NetworkWidget::setUdpPort);
    // TODO: 设置自动监听UDP端口，在此手动发送一次信号
    vBoxLayoutPage->addLayout(hBoxLayoutUdpPortSetting);

    textEditUdpReceivedData->setReadOnly(true);
    vBoxLayoutPage->addWidget(textEditUdpReceivedData);

    this->setLayout(vBoxLayoutPage);
}

NetworkWidget::~NetworkWidget()
{
    LOGD("here");

    if(mavlinkDataProcessor != nullptr)
    {
        mavlinkDataProcessor->stop = true;
        dataProcessThread.quit();
        dataProcessThread.wait();
    }
}

void NetworkWidget::setUdpPort()
{
    LOGD("here");
    if(udpSocket == nullptr){
        udpSocket = new QUdpSocket();
        LOGI("create new UDP socket now");
    }
    int port = lineEditUdpPortSetting->text().toInt();
    udpSocket->bind(QHostAddress::AnyIPv4, port);
    LOGI("bind to UDP port:%d", port);
    connect(udpSocket, &QUdpSocket::readyRead, this, &NetworkWidget::readUdpData);

    // TODO: 动态创建和释放，用按钮决定是解码MavLink还是其他数据
    // TODO: 串口与UDP数据互斥，只能有一个是MavLink的
    mavlinkDataProcessor = new MavlinkDataProcessor;
    mavlinkDataProcessor->moveToThread(&dataProcessThread);
    connect(this, &NetworkWidget::startProcessData, mavlinkDataProcessor, &MavlinkDataProcessor::processData);
    // 该线程结束时销毁
    connect(&dataProcessThread, &QThread::finished, mavlinkDataProcessor, &QObject::deleteLater);
    // 处理数据后会发送信号，在槽函数中更新UI
    qRegisterMetaType<mavlink_message_t>("mavlink_message_t");
    connect(mavlinkDataProcessor, &MavlinkDataProcessor::stringReady, this, &NetworkWidget::updateUdpReceivedTextEdit);
    connect(mavlinkDataProcessor, &MavlinkDataProcessor::attitudeReady, &HomeWidget::getInstance(), &HomeWidget::updateAttitude);
    connect(mavlinkDataProcessor, &MavlinkDataProcessor::messageReady,
            &StatusWidget::getInstance(), &StatusWidget::updateMavlinkMessage);
    //启动线程
    dataProcessThread.start();
    //发射信号，开始执行
    LOGI("emit the signal startProcessData");
    LOGI("UI thread ID:0x%x", QThread::currentThreadId());
    emit startProcessData();
}

qint64 lastPrintLength = 0;
void NetworkWidget::readUdpData()
{
//    qDebug() << "File:" <<  __FILE__ << " Line:"<<  __LINE__ << " Func:" <<  __FUNCTION__;
    QByteArray *array = new QByteArray;
    qint64 readLength;

    //根据可读数据来设置空间大小
    array->resize(udpSocket->bytesAvailable());
    //读取数据
    readLength = udpSocket->readDatagram(array->data(),array->size(),&udpRemoteAddress,&udpRemotePort);
    udpReceivedTotalLength += readLength;
    array->resize(readLength);
    if(udpReceivedTotalLength - lastPrintLength > 100000){
        LOGD("UDP received size in readUdpData:%d", udpReceivedTotalLength);
        lastPrintLength = udpReceivedTotalLength;
    }
    //加锁防止同时访问链表
    mutexListUdpReceivedData.lock();
    listUdpReceivedData.append(array);
    mutexListUdpReceivedData.unlock();
//    qDebug() << "received length: " << readLength << "from Host: " << address << "Port: " << port;
}

void NetworkWidget::updateUdpReceivedTextEdit(QString string)
{
//    qDebug() << "File:" <<  __FILE__ << " Line:"<<  __LINE__ << " Func:" <<  __FUNCTION__;
    textEditUdpReceivedData->append(string);
}
